<template>
  <div
    :class="animate"
    :style="{ height: height, width: width }"
    :id="chartOption.bindingDiv"
    ref="text"
  >
    <template v-for="(item, rowindex) in rows">
      <div :style="rowStyle" :key="rowindex">
        <div :style="colorTop"></div>
        <template v-for="(col, colindex) in item">
          <div
            :style="colorRow"
            :key="colindex"
            @click="fieldClick(col)"
            class="color"
          >
            <div :style="getColorBlock(rowindex, colindex)">
              <div :style="colorText">{{ col.name }}</div>
              <div :style="colorValue">
                <span :style="colorSpan">{{ col.value }}</span>
                <span :style="colorSuffix">{{ col.suffix }}</span>
              </div>
            </div>
          </div>
        </template>
      </div>
    </template>
  </div>
</template>

<script>
import echarts from "echarts";
require("echarts/theme/macarons"); // echarts theme
import resize from "@/views/dashboard/mixins/resize";
import VueEvent from "@/views/tool/datav/VueEvent";
import "../../animate/animate.css";
import { getFormsource } from "@/api/tool/datav/formsource";
import { parseQueryString, fIsUrL } from "../../util/urlUtil";
import { chartApiBar, remoteChartApi,chartBIanalysis } from "@/api/tool/datav/chartApi";
import { websocketCommand } from "../../util/websocket.js";
import { linkChart } from "../../util/LinkageChart";

const animationDuration = 6000;

export default {
  mixins: [resize],
  props: {
    className: {
      type: String,
      default: "chart"
    },
    width: {
      type: String,
      default: "100%"
    },
    height: {
      type: String,
      default: "100%"
    },
    chartOption: {
      type: Object
    },
    drawingList: {
      type: Array
    }
  },
  data() {
    return {
      chart: null,
      dataOption: JSON.parse(JSON.stringify(this.chartOption)),
      rows: [],
      colorheight: "",
      colorwidth: "",
      timer: "",
      wsObj: null,
      wsFlag: false,
      wsTimer: "",
      wsValue: null,
      animate: this.className
    };
  },
  watch: {
    width() {},
    height() {},
    chartOption: {
      deep: true,
      handler(newVal) {
        this.setOptions(JSON.parse(JSON.stringify(newVal)));
      }
    },
    "chartOption.timeout": {
      handler() {
        this.chart = null;
        this.initChart();
      }
    },
    "chartOption.dataSourceType": {
      handler(value) {
        //切换数据源重新连接
        if (value !== "websocket") {
          this.wsFlag = false;
          //每次切换数据源恢复原来动画
          this.animate = this.className;
        }
        if (value !== "url") {
          clearTimeout(this.timer);
        } 
      }
    },
    "chartOption.interfaceKey": {
      handler(newValue, oldValue) {
        //初始化不创建连接，改变接口地址重新创建
        if (oldValue !== undefined && oldValue != "") {
          this.wsValue = null;
          this.closeWs();
          this.createWs();
          this.animate = this.className;
        }
      }
    },
    wsFlag: {
      handler(value) {
        if (!value) {
          this.wsValue = null;
          this.closeWs();
        }
      }
    },
    className: {
      handler(value) {
        this.animate = value;
      }
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.initChart();
    });
  },
  beforeDestroy() {
    this.chart = null;
    clearTimeout(this.timer);
    if (this.wsFlag) {
      this.closeWs();
    }
  },
  computed: {
    rowStyle() {
      let style = {
        width: "100%",
        display: "flex",
        flexDirection: "row",
        height: this.colorheight + "%"
      };
      return style;
    },
    colorTop() {
      const style = { height: this.chartOption.marginTop + "%" };
      return style;
    },
    colorRow() {
      const style = { width: this.colorwidth + "%", height: "100%" };
      return style;
    },
    colorText() {
      let style = {
        justifyContent: this.chartOption.text.left,
        fontSize: this.chartOption.text.size + "px",
        fontFamily: this.chartOption.text.family,
        fontWeight: this.chartOption.text.weight,
        color: this.chartOption.text.color,
        display: "flex",
        alignItems: "center"
      };
      if (
        this.chartOption.textLocate == "left" ||
        this.chartOption.textLocate == "right"
      ) {
        style.width = this.chartOption.text.width + "%";
        style.height = "100%";
        style.lineHeight = "100%";
      } else {
        style.width = "100%";
        style.height = "50%";
        style.lineHeight = "100%";
      }
      return style;
    },
    colorValue() {
      let style = {
        display: "flex",
        alignItems: "center",
        justifyContent: this.chartOption.value.left
      };
      if (
        this.chartOption.textLocate == "left" ||
        this.chartOption.textLocate == "right"
      ) {
        style.width = 100 - this.chartOption.text.width + "%";
        style.height = "100%";
        style.lineHeight = "100%";
      } else {
        style.width = "100%";
        style.height = "50%";
        style.lineHeight = "100%";
      }
      return style;
    },
    colorSpan() {
      let style = {
        fontSize: this.chartOption.value.size + "px",
        fontFamily: this.chartOption.value.family,
        fontWeight: this.chartOption.value.weight,
        color: this.chartOption.value.color,
        letterSpacing: this.chartOption.value.letterSpacing + "px"
      };
      return style;
    },
    colorSuffix() {
      let style = {
        display: "inline-block",
        marginLeft: "5px",
        textAlign: "left",
        fontSize: this.chartOption.suffix.size + "px",
        fontFamily: this.chartOption.suffix.family,
        fontWeight: this.chartOption.suffix.weight,
        color: this.chartOption.suffix.color,
        width: this.chartOption.suffix.width + "%"
      };
      return style;
    }
  },
  methods: {
    initChart() {
      //判断是否开启定时器，当是访问url接口时候并且timeout不为0时候开启定时器
      if (this.timer != "") {
        clearTimeout(this.timer);
      }
      if (
        (this.chartOption.dataSourceType == 'url' || this.chartOption.dataSourceType == 'database') &&
        this.chartOption.timeout > 0
      ) {
        let timerTask = () => {
          this.setOptions(JSON.parse(JSON.stringify(this.chartOption)));
          this.timer = setTimeout(() => {
            timerTask();
          }, this.chartOption.timeout);
        };

        timerTask();
      }else{
        this.setOptions(JSON.parse(JSON.stringify(this.chartOption)));
      }
    },
    setOptions: async function(dataOption) {
      //console.log("=>",dataOption)

      //初始化数据
      //如果不是静态数据就调用接口给staticDataValue赋值
      if (dataOption.dataSourceType == "url" || dataOption.isStaticData == false) {
        let paramJson = parseQueryString(dataOption.requestParameters);

        let interfaceURL = dataOption.interfaceURL;

        dataOption.staticDataValue = await chartApiBar(
          dataOption.requestMethod,
          interfaceURL,
          paramJson,
          dataOption.token
        );
        this.$set(
          this.dataOption,
          "staticDataValue",
          dataOption.staticDataValue
        );

        // dataOption.colorBlock = [];

        //   if(dataOption.colorBlock.length < dataOption.staticDataValue.length){
        //     for(let i=length;i<dataOption.staticDataValue.length;i++){
        //       let cblock={};
        //       cblock.color = 'rgba(0,0,0,0)';
        //       cblock.suffix = '单位';
        //       dataOption.colorBlock.push(cblock);
        //     }
        //   }else if(dataOption.colorBlock.length > dataOption.staticDataValue.length){
        //       dataOption.colorBlock = dataOption.colorBlock.slice(0,dataOption.staticDataValue.length);
        //   }
        //  // VueEvent.$emit('change-color',dataOption.colorBlock);
        //   console.log(dataOption.colorBlock.length);
        //   console.log(dataOption.staticDataValue.length);
      } else if (dataOption.dataSourceType == "database") {
        if (dataOption.database.executeSql != undefined && dataOption.database.executeSql != '') {
          
          let result = [];
          if(dataOption.database.sqlType == 'custom'){
          
            result = await chartBIanalysis(dataOption.database);
          }
          if (result.code == 200) {
            dataOption.staticDataValue = result.data;
            //console.log(dataOption.staticDataValue);
          } else {
            alert("操作数据库错误");
          }
        }
      } else if (dataOption.dataSourceType == "form") {
        if (dataOption.formSource != undefined) {
          let response = await getFormsource(dataOption.formSource.id);
          dataOption.staticDataValue = JSON.parse(response.data.formData);
        }
      } else if (dataOption.dataSourceType == "websocket") {
        if (
          dataOption.interfaceKey != undefined &&
          dataOption.interfaceKey != ""
        ) {
          if (!this.wsFlag) {
            this.wsFlag = true;
            this.wsValue = null;
            this.createWs();
          }
          if (this.wsValue != null) {
            dataOption.staticDataValue = this.wsValue;
          }
        }
      }
      
      let dataValue = [];
      //根据千位分隔符格式化数字
      if (dataOption.isThousand != "false") {
        for (let x in dataOption.staticDataValue) {
          dataOption.staticDataValue[x].value = this.thousandDevide(
            dataOption.staticDataValue[x].value,
            dataOption.isThousand
          );
        }
      } else {
        for (let y in dataOption.staticDataValue) {
          dataOption.staticDataValue[y].value =
            dataOption.staticDataValue[y].value;
        }
      }
      this.rows = this.getRows(dataOption.staticDataValue);
      //数据处理
       if(dataOption.customData != undefined && dataOption.customData != ""){
         try {
             this.$nextTick(() => {
                dataOption.staticDataValue = (
                //里面为要处理的代码块 
                eval(dataOption.customData) 
              
              )(
                dataOption.staticDataValue,
                this.$refs.text
              );
              this.rows = this.getRows(dataOption.staticDataValue);
             
              
            })
          } catch (error) {
            console.log(error)
          }  
       }

      //交互组件配置
      if(dataOption.interactData != undefined && dataOption.interactData != ""){
          try {
             this.$nextTick(() => {
                dataOption.staticDataValue = (
                //里面为要处理的代码块 
                eval(dataOption.interactData) 
              
              )(
                dataOption.staticDataValue,
                this.$refs.text
              );
              this.rows = this.getRows(dataOption.staticDataValue);
             
              
            })
          } catch (error) {
            console.log(error)
          }               
       }

      //  console.log(dataOption.staticDataValue)
      // for(let m in dataOption.colorBlock){
      //     dataOption.staticDataValue[m].suffix = dataOption.colorBlock[m].suffix;
      //   }

      


    },
    getRows(staticDataValue){
      //根据列数计算数据的行数，并按顺序将数据构造成按指定行、列分隔的数组
      let results = [];
      //列数，判断列数不能大于数据数组的总长度
      let colsNum = staticDataValue.length;
      if(this.chartOption.numOfCol < staticDataValue.length){
        colsNum = this.chartOption.numOfCol;
      }
      let col = 0;//颜色块行数
      for(let i = 0;i < staticDataValue.length;){
        let rows = [];
        for(let j = 0; j < colsNum && i < staticDataValue.length; j++){
          //每行数据
          rows.push(staticDataValue[i])
          i++
        }
        results.push(rows)
        col ++ ;
      }
      //每个颜色块宽度占比
      this.colorwidth = (100-this.chartOption.marginLeft*colsNum)/colsNum;

      //每个颜色块高度占比
      this.colorheight = (100-(col)*this.chartOption.marginTop)/(col);
      return results
    },
    thousandDevide(data, devide) {
      //格式化数字
      if (typeof data != "number") {
        return data;
      } else {
        if (!devide) {
          devide = ",";
        }
        var res = data.toString().replace(/\d+/, function(n) {
          // 先提取整数部分
          return n.replace(/(\d)(?=(\d{3})+$)/g, function($1) {
            return $1 + devide;
          });
        });
        return res;
      }
    },
    getColorBlock(rowindex, colindex) {
      //console.log('num=====',this.chartOption.colorBlock);
      let style = {
        width: "100%",
        height: "100%",
        marginLeft: this.chartOption.marginLeft + "%",
        borderRadius: this.chartOption.bradius + "px",
        display: "flex"
      };
      if (this.chartOption.textLocate == "left") {
        style.flexDirection = "row";
      } else if (this.chartOption.textLocate == "right") {
        style.flexDirection = "row-reverse";
      } else if (this.chartOption.textLocate == "top") {
        style.flexDirection = "column";
      } else {
        style.flexDirection = "column-reverse";
      }
      //根据二维数组坐标获取颜色块背景
      //  if(this.chartOption.colorBlock.length > 0){

      //    let num = (colindex) + (this.chartOption.numOfCol* (rowindex+1)) -this.chartOption.numOfCol
      //    style.backgroundColor = this.chartOption.colorBlock[num].color
      //  }

      return style;
    },
    fieldClick(col) {
      //开启图表联动
      if (this.chartOption.isLink == true) {
        //设置参数
        let arrs = JSON.stringify(col);

        //获取绑定的图表
        let bindList = this.chartOption.bindList;

        if (bindList.length > 0) {
          linkChart(this.chartOption.arrName, arrs, bindList, this.drawingList);
        }
      }
      //开启图表下钻
      else if (this.chartOption.isDrillDown == true) {
        //设置参数
        let arrs = JSON.stringify(col);

        //获取绑定的图表
        let drillDownChartOption = this.chartOption.drillDownChartOption;

        if (drillDownChartOption != undefined && drillDownChartOption != null) {
          this.$set(
            this.chartOption.drillDownChartOption.chartOption,
            "requestParameters",
            "drillParam=" + arrs
          );
          //发送下钻消息
          VueEvent.$emit(
            "drill_down_msg",
            this.chartOption.drillDownChartOption
          );
        }
      }
      //开启远程图表控制
      if (this.chartOption.isRemote == true) {
        if (
          this.chartOption.remote != undefined &&
          this.chartOption.remote != null
        ) {
          //设置参数
          let remoteData = { ...this.chartOption.remote };
          remoteData.query = JSON.stringify(col);
          // //调用接口
          remoteChartApi(remoteData);
        }
      }
    },
    //  ws连接成功，后台返回的ws数据
    receiveMsg(e) {
      if (e.action == "chat") {
        // console.log('服务端推送',e);
        this.wsValue = JSON.parse(e.result);
        this.setOptions(JSON.parse(JSON.stringify(this.chartOption)));
      }
    },
    // 建立连接、发起ws请求，以心跳方式，向服务端发送数据
    createWs() {
      this.wsObj = new WebSocket(process.env.VUE_APP_WEBSOCKET);
      // 若为对象类型，以回调方式发送
      websocketCommand(
        this.wsObj,
        "create",
        5000,
        this.chartOption.interfaceKey,
        this.sendHeartBeat,
        this.receiveMsg,
        this.reconnectWs,
        this.wsWarning
      );
    },
    // 断网重连，需要处理的逻辑
    reconnectWs() {
      if (this.wsObj) {
        console.log("%c websocket_reconnect", "color:blue");
        this.createWs();
      }
    },
    // 以回调方式向服务端发送(对象类型的)心跳
    sendHeartBeat() {
      if (this.wsTimer != "") {
        clearTimeout(this.wsTimer);
      }

      let wsTimerTask = () => {
        console.log("发送心跳", "ping");
        let obj = { action: "keep", key: this.chartOption.interfaceKey };
        this.wsObj.send(JSON.stringify(obj));
        this.wsTimer = setTimeout(() => {
          wsTimerTask();
        }, parseInt(process.env.VUE_APP_WEBSOCKET_TIMEOUT));
        this.wsWarning();
      };

      wsTimerTask();
    },
    wsWarning() {
      //如果断开连接则显示组件警告动画并清除计数器
      if (this.wsObj.readyState == 3) {
        this.animate = "warning";
        clearTimeout(this.wsTimer);
      }
    },
    closeWs() {
      clearTimeout(this.wsTimer);
      websocketCommand(
        this.wsObj,
        "close",
        5000,
        this.chartOption.interfaceKey,
        this.sendHeartBeat,
        this.receiveMsg,
        this.reconnectWs,
        this.wsWarning
      );
      this.wsObj = null;
    }
  }
};
</script>
<style ang="scss" scoped>
.color:hover {
  cursor: default;
}
</style>
